package com.bdk.middle.orchestration.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bdk.middle.common.domain.PageDO;
import com.bdk.middle.common.result.ResultDO;
import com.bdk.middle.common.status.ErrorCode;
import com.bdk.middle.common.util.BeanUtilsExtends;
import com.bdk.middle.common.util.Constant;
import com.bdk.middle.orchestration.api.client.AppClientApi;
import com.bdk.middle.orchestration.api.domain.*;
import com.bdk.middle.orchestration.api.query.AppManagerQueryDO;
import com.bdk.middle.orchestration.core.entity.AppImagesEntity;
import com.bdk.middle.orchestration.core.entity.AppManagerEntity;
import com.bdk.middle.orchestration.core.entity.AppModuleEntity;
import com.bdk.middle.orchestration.core.entity.ServiceManagerEntity;
import com.bdk.middle.orchestration.core.mapper.AppImagesMapper;
import com.bdk.middle.orchestration.core.mapper.AppManagerMapper;
import com.bdk.middle.orchestration.core.mapper.AppModuleMapper;
import com.bdk.middle.orchestration.service.AppManagerService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bdk.middle.orchestration.service.FunctionModuleService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Reagan
 * @since 2021-03-12
 */
@RestController
@Service
public class AppManagerServiceImpl extends ServiceImpl<AppManagerMapper, AppManagerEntity> implements AppManagerService, AppClientApi {

    private Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    @Autowired
    private AppManagerMapper appManagerMapper;

    @Autowired
    private AppImagesMapper appImagesMapper;

    @Autowired
    private AppModuleMapper appModuleMapper;

    @Autowired
    private FunctionModuleService functionModuleService;

    @Override
    public ResultDO add(AppManagerDO domain) {

        AppManagerEntity entity = new AppManagerEntity();
        ResultDO result = BeanUtilsExtends.copy(entity, domain);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        int res = -1;
        try {
            res = appManagerMapper.insert(entity);
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(res < 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.APP_MANAGER_ADD_ERROR);
            logger.debug("error code：" + ErrorCode.APP_MANAGER_ADD_ERROR.getCode() + " msg" + ErrorCode.APP_MANAGER_ADD_ERROR.getMsg());
            return result;
        }

        if(domain.getImagesList() != null) {
            result = addImages(entity.getId(), domain.getImagesList());
        }



        return result;
    }

    private ResultDO deleteAppMoudle(String appId) {

        ResultDO result = new ResultDO();

        try {
           appModuleMapper.delete(Wrappers.<AppModuleEntity>lambdaQuery().eq(AppModuleEntity::getAppId, appId));
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        return result;
    }

    public ResultDO setAppModule(AppManagerDO domain) {

        ResultDO result = new ResultDO();

        result = deleteAppMoudle(domain.getId());

        if(!result.isSuccess()) {
            return result;
        }
        int res = -1;

        for(String functionModuleId : domain.getFunctionModuleIds()) {

            AppModuleEntity entity = new AppModuleEntity();
            entity.setAppId(domain.getId());
            entity.setModuleId(functionModuleId);

            try {
                res = appModuleMapper.insert(entity);
            } catch(Exception e) {
                result.setSuccess(false);
                result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
                logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
                return result;
            }

            //判断r的值是否小于0.如果小于0 就代表添加失败
            if(res < 0) {
                result.setSuccess(false);
                result.setErrorCode(ErrorCode.APP_MODULE_ADD_ERROR);
                logger.debug("error code：" + ErrorCode.APP_MODULE_ADD_ERROR.getCode() + " msg" + ErrorCode.APP_MODULE_ADD_ERROR.getMsg());
                return result;
            }
        }
        return result;
    }


    @Override
    public ResultDO edit(AppManagerDO domain) {

        AppManagerEntity entity = new AppManagerEntity();

        ResultDO result = BeanUtilsExtends.copy(entity, domain);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        int res = -1;
        try {
            res = appManagerMapper.updateById(entity);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(res < 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.APP_MANAGER_EDIT_ERROR);
            logger.debug("error code：" + ErrorCode.APP_MANAGER_EDIT_ERROR.getCode() + " msg" + ErrorCode.APP_MANAGER_EDIT_ERROR.getMsg());
            return result;
        }

        if(domain.getImagesList() != null) {
            result = deleteImages(domain.getId());
            if(!result.isSuccess()) {
                return result;
            }
            result = addImages(domain.getId(), domain.getImagesList());
        }

        return result;
    }



    @Override
    public ResultDO get(String id) {

        ResultDO result = new ResultDO();
        AppManagerEntity entity = null;

        try {
            entity = appManagerMapper.selectById(id);
        } catch(Exception e) {
            e.printStackTrace();
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        AppManagerDO domain = getDomain(entity);

        result = getImages(id);

        if(!result.isSuccess()) {
            return result;
        }

        domain.setImagesList((List<AppImagesDO>) result.getModel(ResultDO.FIRST_MODEL_KEY));

        result = getAppFunctionModule(id);
        if(!result.isSuccess()) {
            return result;
        }

        domain.setFunctionModuleList((List<FunctionModuleDO>) result.getModel(ResultDO.FIRST_MODEL_KEY));

        result.setModel(ResultDO.FIRST_MODEL_KEY, domain);

        return result;
    }

    @Override
    public ResultDO remove(String id, String modifier) {

        ResultDO result = new ResultDO();

        AppManagerEntity entity = new AppManagerEntity();

        entity.setId(id);
        entity.setIsDelete(Constant.IS_DELETE);
        entity.setModifiDate(Calendar.getInstance().getTime());
        entity.setModifier(modifier);

        int res = -1;
        try {
            res = appManagerMapper.updateById(entity);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(res < 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.APP_MANAGER_ADD_ERROR);
            logger.debug("error code：" + ErrorCode.APP_MANAGER_EDIT_ERROR.getCode() + " msg" + ErrorCode.APP_MANAGER_EDIT_ERROR.getMsg());
            return result;
        }
        result = deleteAppMoudle(id);

        if(!result.isSuccess()) {
            return result;
        }

        result = deleteImages(id);

        return result;
    }

    public ResultDO updateStatus(String id, int status, String modifier) {

        ResultDO result = new ResultDO();

        AppManagerEntity entity = new AppManagerEntity();

        entity.setId(id);
        entity.setStatus(status);
        entity.setModifiDate(Calendar.getInstance().getTime());
        entity.setModifier(modifier);

        int res = -1;
        try {
            res = appManagerMapper.updateById(entity);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(res < 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.APP_MANAGER_EDIT_ERROR);
            logger.debug("error code：" + ErrorCode.APP_MANAGER_EDIT_ERROR.getCode() + " msg" + ErrorCode.APP_MANAGER_EDIT_ERROR.getMsg());
            return result;
        }

        return result;
    }

    @Override
    public ResultDO find(AppManagerQueryDO query) {

        AppManagerEntity entity = new AppManagerEntity();

        ResultDO result = BeanUtilsExtends.copy(entity,query);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        QueryWrapper<AppManagerEntity> wrapper = new QueryWrapper<AppManagerEntity>(entity);
        if(StringUtils.isNotEmpty(query.getCategoryId())) {
            wrapper.eq("category_id", query.getCategoryId());
        }
        if(StringUtils.isNotEmpty(query.getTenantId())) {
            wrapper.eq("tenant_id", query.getTenantId());
        }

        wrapper.eq("is_delete", Constant.IS_DELETE_FALSE);
        Page<AppManagerEntity> page = new Page<>(query.getCurrentPage(),query.getPageSize());
        IPage<AppManagerEntity> iPage = null;
        try {
            iPage = appManagerMapper.selectPage(page, wrapper);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        List<AppManagerDO> doList = getDomainList(iPage.getRecords());

        PageDO<AppManagerDO> pageDO = new PageDO<>();

        pageDO.setCurrentPage(iPage.getCurrent());
        pageDO.setPageCount(iPage.getPages());
        pageDO.setPageSize(iPage.getSize());
        pageDO.setRowCount(iPage.getTotal());
        pageDO.setData(doList);

        result.setModel(ResultDO.FIRST_MODEL_KEY, pageDO);
        return result;
    }

    private ResultDO addImages(String appId, List<AppImagesDO> dolist) {

        ResultDO result = new ResultDO();

        for(AppImagesDO domain : dolist) {
            AppImagesEntity entity = new AppImagesEntity();
            result = BeanUtilsExtends.copy(entity, domain);
            if(!result.isSuccess()) {
                logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
                return result;
            }
            entity.setAppId(appId);
            int res = -1;
            try {
                res = appImagesMapper.insert(entity);
            } catch(Exception e) {
                result.setSuccess(false);
                result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
                logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
                return result;
            }

            if(res < 0) {
                result.setSuccess(false);
                result.setErrorCode(ErrorCode.APP_IMAGE_ADD_ERROR);
                logger.debug("error code：" + ErrorCode.APP_IMAGE_ADD_ERROR.getCode() + " msg" + ErrorCode.APP_IMAGE_ADD_ERROR.getMsg());
                return result;
            }
        }

        return result;
    }

    private ResultDO deleteImages(String appId) {

        ResultDO result = new ResultDO();

        int res = -1;
        try {
            res = appImagesMapper.delete(Wrappers.<AppImagesEntity>lambdaQuery().eq(AppImagesEntity::getAppId, appId));
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        if(res < 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.APP_IMAGE_ADD_ERROR);
            logger.debug("error code：" + ErrorCode.APP_IMAGE_ADD_ERROR.getCode() + " msg" + ErrorCode.APP_IMAGE_ADD_ERROR.getMsg());
            return result;
        }

        return result;

    }

    private ResultDO getImages(String appId) {

        ResultDO result = new ResultDO();

        List<AppImagesEntity> list = null;
        try {
            list = appImagesMapper.selectList(Wrappers.<AppImagesEntity>lambdaQuery().eq(AppImagesEntity::getAppId, appId));
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        List<AppImagesDO> doList = getImageDomainList(list);
        result.setModel(ResultDO.FIRST_MODEL_KEY, doList);
        return result;
    }

    private ResultDO getAppFunctionModule(String appId) {

        ResultDO result = new ResultDO();

        List<AppModuleEntity> list  = null;

        try {
            list = appModuleMapper.selectList(Wrappers.<AppModuleEntity>lambdaQuery().eq(AppModuleEntity::getAppId, appId));
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        List<FunctionModuleDO> doList = new ArrayList<>();

        for(AppModuleEntity entity : list) {
            result = functionModuleService.get(entity.getModuleId());
            if(!result.isSuccess()) {
                return result;
            }
            doList.add((FunctionModuleDO) result.getModel(ResultDO.FIRST_MODEL_KEY));
        }
        result.setModel(ResultDO.FIRST_MODEL_KEY, doList);
        return result;
    }

    public ResultDO builder(String id) {

        ResultDO result = get(id);

        if(!result.isSuccess()) {
            return result;
        }

        AppManagerDO appManagerDO = (AppManagerDO) result.getModel(ResultDO.FIRST_MODEL_KEY);

        ApplicationDO domain = new ApplicationDO();
        domain.setName(appManagerDO.getTitle());
        domain.setModules(new ArrayList<>());

        for(FunctionModuleDO functionModuleDO : appManagerDO.getFunctionModuleList()) {

            ModuleDO moduleDO = new ModuleDO();
            moduleDO.setName(functionModuleDO.getModuleName());
            moduleDO.setServices(new ArrayList<>());

            for (ServiceManagerDO serviceManagerDO : functionModuleDO.getServiceManagers()) {

                ServiceDO serviceDO = new ServiceDO();
                serviceDO.setName(serviceManagerDO.getServiceName());
                serviceDO.setRequestUrl(serviceManagerDO.getRequestUrl());
                serviceDO.setMethod(serviceManagerDO.getMethod());
                moduleDO.getServices().add(serviceDO);

            }

            domain.getModules().add(moduleDO);
        }
        result.setModel(ResultDO.FIRST_MODEL_KEY, domain);
        return result;
    }

    private AppManagerDO getDomain(AppManagerEntity entity) {
        ResultDO result = new ResultDO();
        //判断房源对象是否为空，为空就返回 空，不为空就进行下面的代码
        if(entity == null) return null;
        AppManagerDO domain = new AppManagerDO();

        if(!result.isSuccess()) {
            return null;
        }
        domain = BeanUtilsExtends.copyProperties(domain, entity) ? domain : null;

        //判断拷贝数据到Dto对象是否成功，如果成功则返回domian，如果不成功就返回空
        return domain;
    }


    private List<AppManagerDO> getDomainList(List<AppManagerEntity> list) {
        //创建一个名为dolist的房源do类型的 list集合
        List<AppManagerDO> doList = new ArrayList<>();

        //判断传入的list的集合的size是否大于0
        if(list.size() > 0) {
            //大于0是，遍历list，创建do类型的对象 调用getdomain方法
            for(AppManagerEntity entity : list) {

                AppManagerDO domain = this.getDomain(entity);

                //判断得到的domain 是否为空 不为空 就往dolist集合里面添加domian 为空就返回空
                if(domain == null) {
                    return null;
                }
                doList.add(domain);
            }
        } else {
            return null;
        }
        return doList;
    }

    private AppImagesDO getImageDomain(AppImagesEntity entity) {
        ResultDO result = new ResultDO();
        //判断房源对象是否为空，为空就返回 空，不为空就进行下面的代码
        if(entity == null) return null;
        AppImagesDO domain = new AppImagesDO();

        if(!result.isSuccess()) {
            return null;
        }
        domain = BeanUtilsExtends.copyProperties(domain, entity) ? domain : null;

        //判断拷贝数据到Dto对象是否成功，如果成功则返回domian，如果不成功就返回空
        return domain;
    }


    private List<AppImagesDO> getImageDomainList(List<AppImagesEntity> list) {
        //创建一个名为dolist的房源do类型的 list集合
        List<AppImagesDO> doList = new ArrayList<>();

        //判断传入的list的集合的size是否大于0
        if(list.size() > 0) {
            //大于0是，遍历list，创建do类型的对象 调用getdomain方法
            for(AppImagesEntity entity : list) {

                AppImagesDO domain = this.getImageDomain(entity);

                //判断得到的domain 是否为空 不为空 就往dolist集合里面添加domian 为空就返回空
                if(domain == null) {
                    return null;
                }
                doList.add(domain);
            }
        } else {
            return null;
        }
        return doList;
    }
}
